import httpx
from typing import Any


class WPClient:
    """
    WordPress JWT 测试客户端
    - 依赖插件：JWT Authentication for WP REST API
    - 主要能力：
        * 登录获取 Token：POST /wp-json/jwt-auth/v1/token
        * 验证 Token：POST /wp-json/jwt-auth/v1/token/validate
        * 获取当前用户：GET /wp-json/wp/v2/users/me
        * （测试）创建用户：POST /wp-json/wp/v2/users 需要管理员权限
    """

    def __init__(self, base_url: str, timeout: float = 15.0, debug: bool = False):
        self.base_url: str = base_url.rstrip("/")
        self.timeout: float = timeout
        self._token: str | None = None
        self.debug: bool = debug

        # 复用连接，性能更好
        self._client = httpx.Client(timeout=self.timeout)

    # ---------------- 公共工具 ----------------

    def set_base_url(self, base_url: str):
        self.base_url = base_url.rstrip("/")

    def set_token(self, token: str | None):
        self._token = token

    def get_token(self) -> str | None:
        return self._token

    def _jwt_headers(self, token: str | None = None) -> dict[str, str]:
        t = token or self._token
        return {"Authorization": f"Bearer {t}"} if t else {}

    def _url(self, path: str) -> str:
        if path.startswith("http"):
            return path
        return f"{self.base_url}{path}"

    # ---------------- 业务接口 ----------------

    def login(self, username: str, password: str) -> tuple[bool, dict[str, Any]]:
        """
        登录并获取 JWT Token
        成功返回 (True, resp_json) 并设置内部 token；失败返回 (False, 错误信息)
        """
        url = self._url("/wp-json/jwt-auth/v1/token")
        try:
            resp = self._client.post(url, data={"username": username, "password": password})
            data = resp.json()
            if resp.status_code == 200 and "token" in data:
                self._token = data["token"]
                return True, data
            # 兼容性：部分站点错误信息字段不同
            return False, {"status_code": resp.status_code, "data": data}
        except httpx.RequestError as e:
            return False, {"error": "network_error", "detail": str(e)}

    def validate_token(self, token: str | None = None) -> tuple[bool, dict[str, Any]]:
        """
        验证 Token 有效性
        """
        url = self._url("/wp-json/jwt-auth/v1/token/validate")
        headers = self._jwt_headers(token)
        if not headers:
            return False, {"error": "no_token", "detail": "未设置 Token"}
        
        # 调试信息
        debug_info = {}
        if self.debug:
            debug_info["request"] = {
                "url": url,
                "headers": {k: v for k, v in headers.items() if k != "Authorization"},  # 不显示token
                "method": "POST"
            }
        
        try:
            resp = self._client.post(url, headers=headers)
            data = resp.json() if resp.content else {}
            
            # 调试信息
            if self.debug:
                debug_info["response"] = {
                    "status_code": resp.status_code,
                    "headers": dict(resp.headers),
                    "content_length": len(resp.content) if resp.content else 0,
                    "raw_response": resp.text if resp.content else ""
                }
            
            # 插件通常返回 200 表示有效
            ok = resp.status_code == 200
            
            # 添加更详细的响应信息
            result = {
                "status_code": resp.status_code,
                "data": data
            }
            
            # 如果启用了调试模式，添加调试信息
            if self.debug:
                result["debug"] = debug_info
            
            # 如果响应失败，添加更多诊断信息
            if not ok:
                if resp.status_code == 403:
                    result["error_type"] = "forbidden"
                    result["suggestion"] = "Token可能已过期或无效"
                elif resp.status_code == 401:
                    result["error_type"] = "unauthorized"
                    result["suggestion"] = "Token认证失败，请重新登录"
                elif resp.status_code == 404:
                    result["error_type"] = "not_found"
                    result["suggestion"] = "JWT插件可能未正确安装或配置"
                else:
                    result["error_type"] = "unknown"
                    result["suggestion"] = f"HTTP状态码: {resp.status_code}"
                    
            return ok, result
        except httpx.RequestError as e:
            error_result = {
                "error": "network_error", 
                "detail": str(e),
                "suggestion": "请检查网络连接和WordPress站点地址是否正确"
            }
            if self.debug:
                error_result["debug"] = debug_info
            return False, error_result

    def get_current_user(self, token: str | None = None) -> tuple[bool, dict[str, Any]]:
        """
        获取当前用户信息（需 Bearer Token）
        """
        url = self._url("/wp-json/wp/v2/users/me")
        headers = self._jwt_headers(token)
        if not headers:
            return False, {"error": "no_token", "detail": "未设置 Token"}
        try:
            resp = self._client.get(url, headers=headers)
            data = resp.json() if resp.content else {}
            ok = resp.status_code == 200
            return ok, {"status_code": resp.status_code, "data": data}
        except httpx.RequestError as e:
            return False, {"error": "network_error", "detail": str(e)}

    def create_user(self, admin_token: str, user_data: dict[str, Any]) -> tuple[bool, dict[str, Any]]:
        """
        （测试）创建用户：POST /wp-json/wp/v2/users
        注意：需要管理员权限（具备创建用户的 capability）
        user_data 示例：
        {
            "username": "newuser",
            "email": "newuser@example.com",
            "password": "Passw0rd!",
            "name": "显示名(可选)",
            "roles": ["subscriber"]  # 可选
        }
        """
        url = self._url("/wp-json/wp/v2/users")
        headers = self._jwt_headers(admin_token)
        if not headers:
            return False, {"error": "no_token", "detail": "未提供管理员 Token"}
        try:
            resp = self._client.post(url, headers=headers, json=user_data)
            data = resp.json() if resp.content else {}
            ok = 200 <= resp.status_code < 300
            return ok, {"status_code": resp.status_code, "data": data}
        except httpx.RequestError as e:
            return False, {"error": "network_error", "detail": str(e)}